package handler

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/olivere/elastic/v7"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"mxshop_srvs/goods_srv/global"
	"mxshop_srvs/goods_srv/model"
	"mxshop_srvs/goods_srv/proto"
)

type GoodsServer struct {
	proto.UnimplementedGoodsServer //为什么要这么写
}

func ModelToResponse(goods model.Goods) proto.GoodsInfoResponse {
	return proto.GoodsInfoResponse{
		Id:              goods.ID,
		CategoryId:      goods.CategoryID,
		Name:            goods.Name,
		GoodsSn:         goods.GoodsSn,
		ClickNum:        goods.ClickNum,
		SoldNum:         goods.SoldNum,
		FavNum:          goods.FavNum,
		MarketPrice:     goods.MarketPrice,
		ShopPrice:       goods.ShopPrice,
		GoodsBrief:      goods.GoodsBrief,
		ShipFree:        goods.ShipFree,
		GoodsFrontImage: goods.GoodsFrontImage,
		IsNew:           goods.IsNew,
		IsHot:           goods.IsHot,
		OnSale:          goods.OnSale,
		DescImages:      goods.DescImages,
		Images:          goods.Images,
		Category: &proto.CategoryBriefInfoResponse{
			Id:   goods.Category.ID,
			Name: goods.Category.Name,
		},
		Brand: &proto.BrandInfoResponse{
			Id:   goods.Brands.ID,
			Name: goods.Brands.Name,
			Logo: goods.Brands.Logo,
		},
	}
}

/*
*
通过关键词 是否热销 是否新品 价格区间,分类等进行筛选
获取商品列表
*/
/*func (s *GoodsServer) GoodsList(ctx context.Context, req *proto.GoodsFilterRequest) (*proto.GoodsListResponse, error) {
	goodsListResponse := &proto.GoodsListResponse{}
	var goodsList []model.Goods
	localDb := global.DB.Model(&model.Goods{})

	//关键词搜索
	if req.KeyWords != "" {
		localDb = localDb.Where("name LIKE ?", "%"+req.KeyWords+"%")
	}
	if req.IsHot {
		localDb = localDb.Where("is_hot = true")
	}
	if req.IsNew {
		localDb = localDb.Where("is_new = true")
	}
	if req.PriceMin > 0 {
		localDb = localDb.Where("shop_price >= ?", req.PriceMin)
	}
	if req.PriceMax > 0 {
		localDb = localDb.Where("shop_price <= ?", req.PriceMax)
	}
	if req.Brand > 0 {
		localDb = localDb.Where("brand_id = ?", req.Brand)
	}
	//分类的实现
	if req.TopCategory > 0 {
		var category model.Category
		if result := global.DB.First(&category, req.TopCategory); result.RowsAffected == 0 {
			return nil, status.Errorf(codes.NotFound, "商品不存在")
		}
		var subQuery string //定义子查询
		if category.Level == 1 {
			subQuery = fmt.Sprintf("select id from category where id in (select id from category where parent_category_id in (select id from category where parent_category_id = %d))", req.TopCategory)
		} else if category.Level == 2 {
			subQuery = fmt.Sprintf("select id from category where id in (select id from category where parent_category_id = %d)", req.TopCategory)
		} else if category.Level == 3 {
			subQuery = fmt.Sprintf("select id from category where id = %d", req.TopCategory)
		}
		localDb = localDb.Where(fmt.Sprintf("category_id in (%s)", subQuery))
	}
	//获取商品数量
	var count int64
	localDb.Count(&count)
	goodsListResponse.Total = int32(count)
	result := localDb.Preload("Category").Preload("Brands").Scopes(Paginate(int(req.Pages), int(req.PagePerNums))).Find(&goodsList)
	if result.Error != nil {
		return nil, result.Error
	}
	for _, goods := range goodsList {
		goodsInfo := ModelToResponse(goods)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfo)
	}
	return goodsListResponse, nil
}*/

/*
*
es和MySQL 联合搜索商品信息
*/
func (s *GoodsServer) GoodsList(ctx context.Context, req *proto.GoodsFilterRequest) (*proto.GoodsListResponse, error) {
	goodsListResponse := &proto.GoodsListResponse{}
	var goodsList []model.Goods
	localDb := global.DB.Model(&model.Goods{})
	q := elastic.NewBoolQuery()

	//关键词搜索
	if req.KeyWords != "" {
		q = q.Must(elastic.NewMultiMatchQuery(req.KeyWords, "name", "goods_brief"))
	}
	//是否热销
	if req.IsHot {
		q = q.Filter(elastic.NewTermQuery("is_hot", req.IsHot))
	}
	//是否新品
	if req.IsNew {
		q = q.Filter(elastic.NewTermQuery("is_new", req.IsNew))
	}
	//最低价格
	if req.PriceMin > 0 {
		q = q.Filter(elastic.NewRangeQuery("shop_price").Gte(req.PriceMin))
	}
	//最高价格
	if req.PriceMax > 0 {
		q = q.Filter(elastic.NewRangeQuery("shop_price").Lte(req.PriceMin))
	}
	//品牌id
	if req.Brand > 0 {
		q = q.Filter(elastic.NewTermsQuery("brands_id", req.Brand))
	}
	//分类的实现
	if req.TopCategory > 0 {
		catetoryIds := make([]interface{}, 0)
		var category model.Category
		if result := global.DB.First(&category, req.TopCategory); result.RowsAffected == 0 {
			return nil, status.Errorf(codes.NotFound, "商品不存在")
		}
		var subQuery string //定义子查询
		if category.Level == 1 {
			subQuery = fmt.Sprintf("select id from category where id in (select id from category where parent_category_id in (select id from category where parent_category_id = %d))", req.TopCategory)
		} else if category.Level == 2 {
			subQuery = fmt.Sprintf("select id from category where id in (select id from category where parent_category_id = %d)", req.TopCategory)
		} else if category.Level == 3 {
			subQuery = fmt.Sprintf("select id from category where id = %d", req.TopCategory)
		}

		type Result struct {
			ID int32
		}
		var results []Result
		global.DB.Model(model.Category{}).Raw(subQuery).Scan(&results)
		for _, re := range results {
			catetoryIds = append(catetoryIds, re.ID)
		}
		//生成terms查询  注意是NewTermsQuery
		q = q.Filter(elastic.NewTermsQuery("category_id", catetoryIds...))
	}
	//es查询总数
	if req.Pages == 0 {
		req.Pages = 1
	}
	switch {
	case req.PagePerNums > 100:
		req.PagePerNums = 100
	case req.PagePerNums <= 0:
		req.PagePerNums = 10
	}
	res, err := global.EsClient.Search().Index(model.EsGoods{}.GetIndexName()).Query(q).From(int(req.Pages)).Size(int(req.PagePerNums)).Do(context.Background())
	if err != nil {
		panic(err)
	}
	//获取总数 以及商品id
	goodsIds := make([]int32, 0)
	total := res.Hits.TotalHits.Value
	goodsListResponse.Total = int32(total)
	for _, value := range res.Hits.Hits {
		esGoods := model.EsGoods{}
		json.Unmarshal(value.Source, &esGoods)
		goodsIds = append(goodsIds, esGoods.ID)
	}

	//分页查询商品列表(当前页数下)
	result := localDb.Preload("Category").Preload("Brands").Find(&goodsList, goodsIds)
	if result.Error != nil {
		return nil, result.Error
	}
	for _, goods := range goodsList {
		goodsInfo := ModelToResponse(goods)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfo)
	}
	return goodsListResponse, nil

	return nil, nil
}

/*
*
批量获取商品
*/
func (c *GoodsServer) BatchGetGoods(ctx context.Context, req *proto.BatchGoodsIdInfo) (*proto.GoodsListResponse, error) {
	goodsListResponse := &proto.GoodsListResponse{}
	var goods []model.Goods
	global.DB.Where(req.Id).Find(&goods)
	for _, good := range goods {
		goodsInfoResponse := ModelToResponse(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}
	goodsListResponse.Total = int32(len(goods))
	return goodsListResponse, nil
}

/*
*
创建商品
*/
func (c *GoodsServer) CreateGoods(ctx context.Context, req *proto.CreateGoodsInfo) (*proto.GoodsInfoResponse, error) {
	var category model.Category
	if catRes := global.DB.First(&category, req.CategoryId); catRes.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "当前分类不存在")
	}
	var brand model.Brands
	if braRes := global.DB.First(&brand, req.BrandId); braRes.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "当前品牌不存在")
	}
	goods := model.Goods{
		CategoryID:      req.CategoryId,
		BrandsID:        req.BrandId,
		OnSale:          req.OnSale,
		ShipFree:        req.ShipFree,
		IsNew:           req.IsNew,
		IsHot:           req.IsHot,
		Name:            req.Name,
		GoodsSn:         req.GoodsSn,
		MarketPrice:     req.MarketPrice,
		ShopPrice:       req.ShopPrice,
		GoodsBrief:      req.GoodsBrief,
		Images:          req.Images,
		DescImages:      req.DescImages,
		GoodsFrontImage: req.GoodsFrontImage,
	}
	tx := global.DB.Begin()
	res := global.DB.Save(&goods)
	if res.Error != nil {
		tx.Rollback()
		return nil, res.Error
	}
	tx.Commit()
	return &proto.GoodsInfoResponse{Id: goods.ID}, nil
}

/*
*
删除商品
*/
func (c *GoodsServer) DeleteGoods(ctx context.Context, req *proto.DeleteGoodsInfo) (*emptypb.Empty, error) {
	if result := global.DB.Delete(&model.Goods{BaseModel: model.BaseModel{ID: req.Id}}, req.Id); result.Error != nil {
		zap.S().Errorf("delete goods error:{}", result.Error)
		return nil, status.Errorf(codes.NotFound, "删除商品失败")
	}
	return nil, nil
}

/*
*
更新商品
*/
func (c *GoodsServer) UpdateGoods(ctx context.Context, req *proto.CreateGoodsInfo) (*emptypb.Empty, error) {
	//判断商品是否存在
	var goods model.Goods
	if goodsRes := global.DB.First(&goods, req.Id); goodsRes.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "当前商品不存在")
	}
	//判断分类是否存在
	var category model.Category
	if catRes := global.DB.First(&category, req.CategoryId); catRes.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "当前分类不存在")
	}
	//判断品牌是否存在
	var brand model.Brands
	if braRes := global.DB.First(&brand, req.BrandId); braRes.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "当前品牌不存在")
	}
	/*if req.CategoryId > 0 {
		goods.CategoryID = req.CategoryId
	}
	if req.BrandId > 0 {
		goods.BrandsID = req.CategoryId
	}*/
	if req.OnSale {
		goods.OnSale = req.OnSale
	}
	if req.ShipFree {
		goods.ShipFree = req.ShipFree
	}
	if req.IsNew {
		goods.IsNew = req.IsNew
	}
	if req.IsHot {
		goods.IsHot = req.IsHot
	}
	if req.Name != "" {
		goods.Name = req.Name
	}
	if req.Name != "" {
		goods.Name = req.Name
	}
	if req.GoodsSn != "" {
		goods.GoodsSn = req.GoodsSn
	}
	if req.MarketPrice > 0 {
		goods.MarketPrice = req.MarketPrice
	}
	if req.ShopPrice > 0 {
		goods.ShopPrice = req.ShopPrice
	}
	if len(req.Images) > 0 {
		goods.Images = req.Images
	}
	if len(req.DescImages) > 0 {
		goods.DescImages = req.DescImages
	}
	if len(req.GoodsFrontImage) > 0 {
		goods.GoodsFrontImage = req.GoodsFrontImage
	}
	tx := global.DB.Begin()
	res := global.DB.Save(&goods)
	if res.Error != nil {
		tx.Rollback()
		return nil, res.Error
	}
	tx.Commit()
	return &emptypb.Empty{}, nil
}

/*
*
获取商品详情
*/
func (c *GoodsServer) GetGoodsDetail(ctx context.Context, req *proto.GoodInfoRequest) (*proto.GoodsInfoResponse, error) {
	var goods model.Goods
	if result := global.DB.Preload("Category").Preload("Brands").First(&goods, req.Id); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "找不到当前商品")
	}
	response := ModelToResponse(goods)
	return &response, nil
}
